package ttt;

import java.util.function.Function;
import java.util.function.Supplier;

public class Lazy<T> implements Supplier<T> {

    private final Supplier<? extends T> instance;

    private T value;

    private Lazy(Supplier<? extends T> instance) {
        this.instance = instance;
    }

    public static <T> Lazy<T> of(Supplier<? extends T> instance) {
        return new Lazy<>(instance);
    }

    @Override
    public synchronized T get() {
        if (value == null) {
            T newValue = instance.get();
            if (newValue == null) {
                throw new IllegalStateException("Lazy value can not is null!");
            }
            value = newValue;
        }
        return value;
    }

    // 函子
    public <S> Lazy<S> map(Function<? super T, ? extends S> mapper) {
        return Lazy.of(() -> mapper.apply(get()));
    }

    // 单子
    public <S> Lazy<S> flatMap(Function<? super T, Lazy<? extends S>> mapper) {
        return Lazy.of(() -> mapper.apply(get()).get());
    }
}
